/*
 *  Character.h
 *  initiativeTracker
 *
 *  Created by Sam Jaffe on 5/5/12.
 *  Copyright 2012 WPI. All rights reserved.
 *
 */

#pragma once

#include <string>
#include <typeinfo>

#define CHARACTER_STATUS_SIZE 14

const int blinded = 0;
const int dazed = 1;
const int deafened = 2;
const int dominated = 3;
const int immobilized = 4;
const int petrified = 5;
const int prone = 6;
const int restrained = 7;
const int slowed = 8;
const int stunned = 9;
const int unconscious = 10;
const int weakened = 11;
const int marked = 12;
const int cursed = 13;

class Character {
private:
    bool delay;
    std::string name;
    unsigned short ac, fort, ref, will, dot, hp_max;
    short init, dis, hp;
    const short idn;
    bool status[CHARACTER_STATUS_SIZE];
    
public:
    Character();
    Character(const short idn);
    Character(const Character& that, const short idn);
    virtual ~Character();
    
    const bool equals(Character* c) const;
    
    virtual void setName(const std::string name);
    virtual const std::string getName() const;
    
    void setHp(const short hp);
    virtual void modHp(const short hp);
    const unsigned short getHp() const;
    
    virtual void setHp_max(const unsigned short hp_max);
    const unsigned short getHp_max() const;
    
    void setAc(const unsigned short ac);
    const unsigned short getAc() const;
    
    void setFort(const unsigned short fort);
    const unsigned short getFort() const;
    
    void setRef(const unsigned short ref);
    const unsigned short getRef() const;
    
    void setWill(const unsigned short will);
    const unsigned short getWill() const;
    
    void setInit(const short init);
    const short getInit() const;
    virtual void nullInit();
    
    const short getId() const;
    
    void setDot(const unsigned short dot);
    const unsigned short getDot() const;
    
    void setDis(const short dis);
    const short getDis() const;
    
    const bool isDelayed() const;
    void checkDelayed();
    
    bool* getStatus();
    const bool is(int status_index) const;
    Character& operator <<(const int index);
    Character& operator >>(const int index);
    
    virtual const std::string toXML() const;
    const int hpCode() const;
    virtual const int baseCode() const;
    const int defenseCode() const;
    const int statusCode() const;
    void decodeStatus(const int stats);
    
    virtual const std::string getType() const;
};

class NPC : public Character {
private:
    bool allied;
    unsigned short count;
    std::string full_name;
    
public:
    NPC();
    NPC(bool isAllied);
    NPC(short idn, bool isAllied);
    NPC(bool isAllied, unsigned short count);
    NPC(short idn, bool isAllied, unsigned short count);
    NPC(const NPC& that, const short idn);
    ~NPC();
    
    const bool isAllied() const;
    
    void setCount(unsigned short count);
    const unsigned short getCount() const;
    
    const std::string getName() const;
    
    const std::string getShortName() const;
    
    void setName(const std::string name);
    
    void setFull_name();
    
    const std::string getType() const;
    
    const std::string baseCode() const;
};

class PC : public Character {
private:
    std::string player;
    unsigned short surgeMax, surgeLeft, surgeVal;
    short temp;
    
public:
    PC();
    PC(unsigned short idn);
    ~PC();
    
    void modHp(const short hp);
    void recover(const unsigned short health);
    const unsigned short surge(const unsigned short bonus);
    
    void setPlayer(const std::string player);
    const std::string getPlayer() const;
    
    void setHp_max(const unsigned short hp_max);
    
    const unsigned short getSurgevalue() const;
    
    void setSurgeMax(const unsigned short surgeMax);
    const unsigned short getSurgeMax() const;
    
    void setSurgeLeft(const unsigned short surgeLeft);
    const unsigned short getSurgeLeft() const;
    
    void setTemp(const short newtemp);
    void modTemp(const short temp);
    const short getTemp() const;
    void nullTemp();
    void nullInit();
    
    const std::string getType() const;
    const std::string playerData() const;
    const std::string toXML() const;
};

#pragma mark Getters/Setters
inline const bool Character::equals(Character* c) const {
    return idn == c->idn;
}

inline void Character::setName(const std::string name) {
    this -> name = name;
}

inline const std::string Character::getName() const {return name;}

inline void Character::setHp(const short hp) {this -> hp = hp;}
inline void Character::modHp(const short hp) {this -> hp -= hp;}
inline const unsigned short Character::getHp() const {return hp;}

inline void Character::setHp_max(const unsigned short hp_max) {
    this -> hp_max = hp_max;
}
inline const unsigned short Character::getHp_max() const {return hp_max;}

inline void Character::setAc(const unsigned short ac) {this -> ac = ac;}
inline const unsigned short Character::getAc() const {return ac;}

inline void Character::setFort(const unsigned short fort) {
    this -> fort = fort;
}
inline const unsigned short Character::getFort() const {return fort;}

inline void Character::setRef(const unsigned short ref) {this -> ref = ref;}
inline const unsigned short Character::getRef() const {return ref;}

inline void Character::setWill(const unsigned short will) {
    this -> will = will;
}
inline const unsigned short Character::getWill() const {return will;}

inline void Character::setInit(const short init) {this -> init = init;}
inline const short Character::getInit() const {return init;}
inline void Character::nullInit() {init = 0;}

inline const short Character::getId() const {return idn;}

inline void Character::setDot(const unsigned short dot) {this -> dot = dot;}
inline const unsigned short Character::getDot() const {return dot;}

inline void Character::setDis(const short dis) {this -> dis = dis;}
inline const short Character::getDis() const {return dis;}

inline const bool Character::isDelayed() const {return delay;}
inline void Character::checkDelayed() {delay = true;}

inline bool* Character::getStatus() {return status;}

inline const bool Character::is(int status_index) const {
    return status[status_index];
}

//---------------------------

inline const bool NPC::isAllied() const {return allied;}

inline const unsigned short NPC::getCount() const {return count;}

inline const std::string NPC::getName() const {
    return full_name;
}

inline const std::string NPC::getShortName() const {
    return Character::getName();
}

inline const std::string NPC::getType() const {
    return allied ? "friend" : "foe";
}

//---------------------------

inline void PC::setPlayer(const std::string player) {this -> player = player;}
inline const std::string PC::getPlayer() const {return player;}

inline const unsigned short PC::getSurgevalue() const {return surgeVal;}

inline void PC::setSurgeMax(const unsigned short surgeMax) {
    this -> surgeMax = surgeMax;
}
inline const unsigned short PC::getSurgeMax() const {return surgeMax;}

inline void PC::setSurgeLeft(const unsigned short surgeLeft) {
    this -> surgeLeft = surgeLeft;
}
inline const unsigned short PC::getSurgeLeft() const {return surgeLeft;}
inline const short PC::getTemp() const {return temp;}
inline void PC::modTemp(const short temp) {this -> temp -= temp;}
inline void PC::nullTemp() {temp = 0;}
inline void PC::nullInit() {Character::nullInit(); nullTemp();}

inline const std::string PC::getType() const {return "player";}

#pragma mark typeinfo

const std::string pc_type(typeid(PC()).name());
const std::string npc_type(typeid(NPC()).name());

